package com.rtos.model.device;

import com.rtos.vo.dat.DeviceAllocationTableVO;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * @program: RTOS
 * @description:
 * @Author: Baiye
 * @Date: 2021-10-07 22:40
 **/
public class Device {
    private StringProperty A1;
    private StringProperty A2;
    private StringProperty B1;
    private StringProperty B2;
    private StringProperty B3;
    private StringProperty C1;
    private StringProperty C2;
    private StringProperty C3;
    //以上为设备的状态字段，值为free或uid
    private ObservableList<QueueItem> QueueA;//A设备的等待队列
    private ObservableList<QueueItem> QueueB;
    private ObservableList<QueueItem> QueueC;
    private static Device device;

    private Device() {
        A1 = new SimpleStringProperty();
        A2 = new SimpleStringProperty();
        B1 = new SimpleStringProperty();
        B2 = new SimpleStringProperty();
        B3 = new SimpleStringProperty();
        C1 = new SimpleStringProperty();
        C2 = new SimpleStringProperty();
        C3 = new SimpleStringProperty();

        QueueA = FXCollections.observableArrayList();
        QueueB = FXCollections.observableArrayList();
        QueueC = FXCollections.observableArrayList();
        deviceTableInitial();
    }

    public static Device getInstance() {
        /**
         * @author: Baiye
         * @description: 单例模式
         * @Date :2021-10-07 23:24
         * @Return: com.device.Device
         */
        if (device == null) {
            device = new Device();
        }
        return device;
    }

    public ObservableList<QueueItem> getQueueA() {
        return QueueA;
    }

    public ObservableList<QueueItem> getQueueB() {
        return QueueB;
    }

    public ObservableList<QueueItem> getQueueC() {
        return QueueC;
    }


    private void deviceTableInitial() {
        /**
         * @author: Baiye
         * @description:设备状态表的初始化
         * @Date :2021-10-07 22:49
         * @Return: void
         */
        A1.set("free");
        A2.set("free");
        B1.set("free");
        B2.set("free");
        B3.set("free");
        C1.set("free");
        C2.set("free");
        C3.set("free");
    }

    private boolean isFree(int index) {
        /**
         * @author: Baiye
         * @description:检测某设备是否空闲
         * @Date :2021-10-07 23:12
         * @Param index：设备号
         * @Return: boolean
         */
        switch (index) {
            case 1:
                return A1.get().equals("free");
            case 2:
                return A2.get().equals("free");
            case 3:
                return B1.get().equals("free");
            case 4:
                return B2.get().equals("free");
            case 5:
                return B3.get().equals("free");
            case 6:
                return C1.get().equals("free");
            case 7:
                return C2.get().equals("free");
            case 8:
                return C3.get().equals("free");
            default:
                return false;
        }
    }

    public int applyA(QueueItem a) {
        /**
         * @author: Baiye
         * @description:申请A类设备
         * @Date :2021-10-08 20:50
         * @Param a: 申请的格式，与进入等待队列的格式相同。
         * @Return: int 设备号
         */
        if (isFree(1)) {
            A1.set(a.getUid());
            return 1;
        } else if (isFree(2)) {
            A2.set(a.getUid());
            return 2;
        } else {
            QueueA.add(a);
            StringProperty waitingProcess1 = DeviceAllocationTableVO.a1.waitingProcess;
            StringProperty waitingProcess2 = DeviceAllocationTableVO.a2.waitingProcess;
            waitingProcess1.set(waitingProcess1.get() + a.getUid() + " ");
            waitingProcess2.set(waitingProcess2.get() + a.getUid() + " ");
            return 9;
        }
    }

    public int applyB(QueueItem b) {
        if (isFree(3)) {
            B1.set(b.getUid());
            return 3;
        } else if (isFree(4)) {
            B2.set(b.getUid());
            return 4;
        } else if (isFree(5)) {
            B3.set(b.getUid());
            return 5;
        } else {
            QueueA.add(b);
            StringProperty waitingProcess1 = DeviceAllocationTableVO.b1.waitingProcess;
            StringProperty waitingProcess2 = DeviceAllocationTableVO.b2.waitingProcess;
            StringProperty waitingProcess3 = DeviceAllocationTableVO.b3.waitingProcess;
            waitingProcess1.set(waitingProcess1.get() + b.getUid() + " ");
            waitingProcess2.set(waitingProcess2.get() + b.getUid() + " ");
            waitingProcess2.set(waitingProcess3.get() + b.getUid() + " ");
            return 9;
        }
    }

    public int applyC(QueueItem c) {
        if (isFree(6)) {
            C1.set(c.getUid());
            return 6;
        } else if (isFree(7)) {
            C2.set(c.getUid());
            return 7;
        } else if (isFree(8)) {
            C3.set(c.getUid());
            return 8;
        } else {
            QueueA.add(c);
            StringProperty waitingProcess1 = DeviceAllocationTableVO.c1.waitingProcess;
            StringProperty waitingProcess2 = DeviceAllocationTableVO.c2.waitingProcess;
            StringProperty waitingProcess3 = DeviceAllocationTableVO.c3.waitingProcess;
            waitingProcess1.set(waitingProcess1.get() + c.getUid() + " ");
            waitingProcess2.set(waitingProcess2.get() + c.getUid() + " ");
            waitingProcess2.set(waitingProcess3.get() + c.getUid() + " ");
            return 9;
        }
    }

    private synchronized int[] nextApply(int type) {
        /**
         * @author: Baiye
         * @description:
         * @Date :2021-10-08 23:01
         * @Param type: 设备号
         * @Return: int[]
         */
        QueueItem queueItem;//free之后的节点
        switch (type) {
            case 1:
            case 2:
                queueItem = QueueA.remove(0);
                dequeWaitingQueueVO("A");
                applyA(queueItem);
                break;
            case 3:
            case 4:
            case 5:
                queueItem = QueueB.remove(0);
                dequeWaitingQueueVO("B");

                applyB(queueItem);
                break;
            case 6:
            case 7:
            case 8:
                queueItem = QueueC.remove(0);
                dequeWaitingQueueVO("C");

                applyC(queueItem);
                break;
            default:
                queueItem = null;
                break;
        }
        int[] awake = new int[2];
        awake[0] = type;
        awake[1] = queueItem.getTime();
        return awake;
    }

    public int[] freeA(String uid) {
        /**
         * @author: Baiye
         * @description:
         * @Date :2021-10-08 22:43
         * @Param uid: 进程标识符
         * @Return: int[]
         */
        if (uid.equals(A1.get())) {
            A1.set("free");
            if (!QueueA.isEmpty()) {
                return nextApply(1);
            }
            return null;
        } else if (uid.equals(A2.get())) {
            A2.set("free");
            if (!QueueA.isEmpty()) {
                return nextApply(2);
            }
            return null;
        } else {
            return null;
        }
    }

    public int[] freeB(String uid) {
        /**
         * @author: Baiye
         * @description:
         * @Date :2021-10-08 23:20
         * @Param uid: 进程标识符
         * @Return: int[]
         */
        if (uid.equals(B1.get())) {
            B1.set("free");
            if (!QueueB.isEmpty()) {
                return nextApply(3);
            }
            return null;
        } else if (uid.equals(B2.get())) {
            B2.set("free");
            if (!QueueB.isEmpty()) {
                return nextApply(4);
            }
            return null;
        } else if (uid.equals(B3.get())) {
            B3.set("free");
            if (!QueueB.isEmpty()) {
                return nextApply(5);
            }
            return null;
        } else {
            return null;
        }
    }

    public int[] freeC(String uid) {
        /**
         * @author: Baiye
         * @description:
         * @Date :2021-10-08 23:22
         * @Param uid: 进程标识符
         * @Return: int[]
         */
        if (uid.equals(C1.get())) {
            C1.set("free");
            if (!QueueC.isEmpty()) {
                return nextApply(6);
            }
            return null;
        } else if (uid.equals(C2.get())) {
            C2.set("free");
            if (!QueueC.isEmpty()) {
                return nextApply(7);
            }
            return null;
        } else if (uid.equals(C3.get())) {
            C3.set("free");
            if (!QueueC.isEmpty()) {
                return nextApply(8);
            }
            return null;
        } else {
            return null;
        }
    }

    public boolean[] freeDevice() {
        /**
         * @author: Baiye
         * @description:用于显示，检测可使用设备，返回一个boolean数组
         * @Date :2021-10-12 21:00
         * @Return: int[]
         */
        boolean freedevice[] = new boolean[8];
        for (int i = 0; i < 8; i++) {
            freedevice[i] = isFree(i + 1);

        }
        return freedevice;
    }

    public String usingProcesses(int index) {
        /**
         * @author: Baiye
         * @description:
         * @Date :2021-10-12 21:08
         * @Param index: 设备号，1~8代表A1~C3     如果设备空闲，则返回空串
         * @Return: String
         */
        switch (index) {
            case 1:
                return A1.get().equals("free") ? "" : A1.get();
            case 2:
                return A2.get().equals("free") ? "" : A2.get();
            case 3:
                return B1.get().equals("free") ? "" : B1.get();
            case 4:
                return B2.get().equals("free") ? "" : B2.get();
            case 5:
                return B3.get().equals("free") ? "" : B3.get();
            case 6:
                return C1.get().equals("free") ? "" : C1.get();
            case 7:
                return C2.get().equals("free") ? "" : C2.get();
            case 8:
                return C3.get().equals("free") ? "" : C3.get();
            default:
                return "非法设备号";
        }
    }

    private ArrayList getAQueue() {
        ArrayList processUid = new ArrayList<String>();
        QueueA.forEach(item -> {
            processUid.add(item.getUid());
        });
        return processUid;
    }

    private ArrayList getBQueue() {
        ArrayList processUid = new ArrayList<String>();
        QueueB.forEach(item -> {
            processUid.add(item.getUid());
        });
        return processUid;
    }

    private ArrayList getCQueue() {
        ArrayList processUid = new ArrayList<String>();
        QueueC.forEach(item -> {
            processUid.add(item.getUid());
        });
        return processUid;
    }

    public ArrayList waitingProcesses(int type) {
        /**
         * @author: Baiye
         * @description:获取不同类型的设备的等待序列
         * @Date :2021-10-12 21:42
         * @Param type: A类型 1  B类型 2  C 类型 3
         * @Return: ArrayList  等待进程的uid
         */
        switch (type) {
            case 1:
                return getAQueue();
            case 2:
                return getBQueue();
            case 3:
                return getCQueue();
            default:
                return null;
        }
    }

    public synchronized void dequeWaitingQueueVO(String deviceName) {
        switch (deviceName) {
            case "A": {
                DeviceAllocationTableVO.a1.waitingProcessProperty().set(QueueA.toString());
                DeviceAllocationTableVO.a2.waitingProcessProperty().set(QueueA.toString());
                break;
            }
            case "B": {
                DeviceAllocationTableVO.b1.waitingProcessProperty().set(QueueB.toString());
                DeviceAllocationTableVO.b2.waitingProcessProperty().set(QueueB.toString());
                DeviceAllocationTableVO.b3.waitingProcessProperty().set(QueueB.toString());
                break;
            }
            case "C": {
                DeviceAllocationTableVO.c1.waitingProcessProperty().set(QueueC.toString());
                DeviceAllocationTableVO.c2.waitingProcessProperty().set(QueueC.toString());
                DeviceAllocationTableVO.c3.waitingProcessProperty().set(QueueC.toString());
                break;
            }
            default: {

            }

        }

    }




    public StringProperty a1Property() {
        return A1;
    }

    public StringProperty a2Property() {
        return A2;
    }

    public StringProperty b1Property() {
        return B1;
    }

    public StringProperty b2Property() {
        return B2;
    }

    public StringProperty b3Property() {
        return B3;
    }

    public StringProperty c1Property() {
        return C1;
    }

    public StringProperty c2Property() {
        return C2;
    }

    public StringProperty c3Property() {
        return C3;
    }
}
